Skip to content

Conversation

@maddie927
Copy link
Member

@maddie927 maddie927 commented Aug 7, 2020

Button2 was one of the first components using emotion and LumiComponent and it shows. Updating it to work more like Text2.

  • onPress uses Aff to control the button loading state, use liftEffect to bypass this behavior
  • default/primary button style
  • secondary style
  • link style
  • loading styles
  • onPress, submit, reset, + other button modifiers

@maddie927 maddie927 self-assigned this Aug 7, 2020
@maddie927 maddie927 force-pushed the madeline/button-cleanup branch from 04dd9ff to 38bee6b Compare August 8, 2020 02:28
@maddie927 maddie927 force-pushed the madeline/button-cleanup branch from 38bee6b to 52edf80 Compare August 8, 2020 02:29
@maddie927 maddie927 requested a review from arthurxavierx August 8, 2020 02:36
@maddie927 maddie927 marked this pull request as ready for review August 8, 2020 22:53
@maddie927 maddie927 force-pushed the madeline/button-cleanup branch from deeaf25 to c8760a8 Compare August 8, 2020 22:56
@maddie927 maddie927 force-pushed the madeline/button-cleanup branch from d249161 to 1e9244e Compare August 9, 2020 04:44
-- | Using `onPress` on a button multiple times chains the effects together
-- | from the first applied, out.
onPress :: forall c. Aff Unit -> ButtonModifier c
onPress a = propsModifier \props -> props { onPress = props.onPress *> a }
Copy link
Member Author

@maddie927 maddie927 Aug 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not be necessary but it seemed like it could be useful to build a button with some base behavior and pass it to something else to add its own behavior, a little bit like DOM event bubbling. This seems like the right compose direction to me but I'm curious what anyone else things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this! Maybe if you want we could also expose a more flexible variant like this?

onPress' :: forall c. (Aff Unit -> Aff Unit) -> ButtonModifier c
onPress' f = propsModifier \props -> props { onPress = f props.onPress }

Not sure if it would be useful though.

$ css
{ zIndex: px ziButtonGroup
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this pattern, thanks @arthurxavierx! These styles feel a lot safer bound to a specific component type.

Copy link
Contributor

@arthurxavierx arthurxavierx Aug 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The caveat here is that modifiers of type forall c. ButtonGroupModifier c can be applied to any component, so maybe this alternative is safer?

type ButtonGroupModifier c = forall r. PropsModifier (buttonGroupComponent :: c | r)

And for every component we have (textComponent :: c | r), (buttonComponent :: c | r), etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, true. I wonder if PropsModifier should contain the (component :: c | props).. then it'd be as general as it is now by default so long as c is left open, but locked to a specific component as soon as you set c, and we wouldn't have the redundant XYZModifier types.

Related- I was also wondering if there was a better way to type loadingContent, it didn't fit into ButtonModifier because of the other prop constraints. It works as is, the inconsistent type aliases just seemed a little weird.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XYZModifier types are also kind of a weird pattern to me. It's just duck typing actually, because we're saying that such and such modifiers apply to any component that has those props (and only to those), and it breaks in the case where a related component has different props (like with loadingContent).

I think that what we want is primarily a way of constraining modifiers to certain components in a hierarchy, it seems we don't have to care about the props like that, so maybe another way of doing it could be something like this?

type ButtonModifier props = forall c. IsButton c => PropsModifier (component :: c | props)

class IsButton c
instance IsButton Button
instance IsButton LinkButton

Not sure how type inference would be affected by that though…

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a phantom type like PropsModifier Button r as well? Going to merge this as is for now though, since it doesn't affect usage much.

Copy link
Contributor

@arthurxavierx arthurxavierx Aug 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately PropsModifier cannot have a phantom type parameter because it's a type synonym, so that PropsModifier Button r and PropsModifier Text r would be the same type (unless, of course, that parameter were used in the definition of PropsModifier).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right

Copy link
Contributor

@arthurxavierx arthurxavierx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! I really like some of the helper modifiers like onPress, ariaLabel, submit, etc.

, hueDisabled :: Color
, white :: Color
}
shade { hue, white, black } =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems quite specific to the Button and ButtonGroup components. Maybe we should call it buttonShades or move it somewhere else?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh haha, I moved it here because it didn't seem buttons specific. Like part of the theme is all our current colors/hues, and this sort of expands each one into a wider range of related colors. I also wondered if it'd be better to move this function into the theme so it can be replaced.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm I see… I can see the use for hueDarker, hueDarkest, and hueDisabled, but maybe we should grab grey1andgrey2from the theme itself? We alredy haveblack1andblack2`.

(this is totally non-blocking btw, just pure nitpicking)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. We should probably expand all the colors instead of just black if we can do it algorithmically, or leave the theme colors as-is and restrict button color to those predefined ones. The whole theme idea could use some work, like making it available to design and having more things use it so it doesn't look silly as values change, dark mode, etc.

@maddie927 maddie927 merged commit 1e57196 into main Aug 11, 2020
@maddie927 maddie927 deleted the madeline/button-cleanup branch August 11, 2020 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants